﻿#include "rolemanager.h"
#include "baserole.h"
#include "basemap.h"
#include "monsterrole.h"
#include "mapmanager.h"
#include "common/common.h"

#include <QJsonDocument>
#include <QDomDocument>
#include <QFile>

RoleManager::RoleManager()
{

}

RoleManager::~RoleManager()
{
    deleteAllMonsters();
    deleteAllPlayers();
}

/**
 * @brief RoleManager::loadMonsterFromXML 从XML中导入怪物配置
 * @param filepath
 * @return
 */
bool RoleManager::loadMonsterFromXML(QString filepath)
{
    if(filepath == "") return false;

    QDomDocument doc;
    QFile file(filepath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return false;
    }

    if (!doc.setContent(&file)) {
        file.close();
        return false;
    }

    QDomElement root = doc.documentElement();
    QDomNode n = root.firstChild();
    while (!n.isNull())
    {
        if (n.isElement()) {
            QDomElement e = n.toElement();
            if (e.tagName() == "monsterinfo")
            {
                int startid = e.attribute("startid").toInt();
                int maxcount = e.attribute("maxcount").toInt();
                QString name = e.attribute("name");
                int guarddistance = e.attribute("guarddistance").toInt();
                int attackdistance = e.attribute("attackdistance").toInt();
                int attacktimespace = e.attribute("attacktimespace").toInt();
                int blood = e.attribute("blood").toInt();
                int defense = e.attribute("defense").toInt();
                int escaperate = e.attribute("escaperate").toInt();
                float selfhealing = e.attribute("selfhealing").toFloat();
                QString shapeinfo = e.attribute("shape");

                // 得到可以使用的弹药类型
                QStringList bullets = e.attribute("bullets").split(",");
                QVector<int> bulletArray;
                for(int k=0;k<bullets.size();k++) bulletArray.push_back(bullets[k].toInt());

                for(int i=0;i<maxcount;i++)
                {
                    MonsterRole *pMonsterRole = new MonsterRole();
                    pMonsterRole->setName(name);
                    pMonsterRole->setViewRect(QRect(QPoint(0,0),
                                                    MapManager::getSingleton().getViewSize()));
                    pMonsterRole->setID(startid+i);
                    pMonsterRole->setGuardDistance(guarddistance);
                    pMonsterRole->setAttackDistance(attackdistance);
                    pMonsterRole->setUsingBullets(bulletArray);
                    pMonsterRole->setAttackTimeSpace(attacktimespace);
                    pMonsterRole->setBlood(blood);
                    pMonsterRole->setDefense(defense);
                    pMonsterRole->setSelfHealing(selfhealing);
                    pMonsterRole->setShape(shapeinfo);
                    pMonsterRole->setEscaperate(escaperate);

                    QDomNode n2 = n.firstChild();
                    while (!n2.isNull())
                    {
                        if (n2.isElement())
                        {
                            QDomElement e = n2.toElement();
                            if (e.tagName() == "activitymap")
                            {
                                int mapid = e.attribute("mapid").toInt();
                                QRect activityrect = convertStringToRect(e.attribute("activityrect"));

                                pMonsterRole->addActivityMap(mapid,activityrect);

                                //activityRectString+=QString::asprintf("%d:%d,%d,%d,%d;",mapid,
                                //                                      activityrect.x(),activityrect.y(),
                                //                                      activityrect.width(),activityrect.height());
                            }
                        }

                        n2 = n2.nextSibling();
                    }

                    mFreeMonsterList.push_back(pMonsterRole);
                }

                print_log(LOG_INFO,
                          QString::fromLocal8Bit("导入NPC:")+
                                   name+
                                   QString::fromLocal8Bit(" 开始ID:")+
                                   QString::asprintf("%d",startid)+
                                   QString::fromLocal8Bit(" 数量:")+
                                   QString::asprintf("%d",maxcount)+
                                   QString::fromLocal8Bit(" 警戒,攻击距离:")+
                                   QString::asprintf("%d,%d",guarddistance,attackdistance)+
                                   QString::fromLocal8Bit(" 使用子弹:")+
                                   e.attribute("bullets")+
                                   QString::fromLocal8Bit(" 攻击时间，血量，防御，自愈能力:")+
                                   QString::asprintf("%d,%d,%d,%f",attacktimespace,blood,defense,selfhealing)+
                                   QString::fromLocal8Bit(" 形状规则:")+
                                   shapeinfo,
                          "1|0|1");


            }
        }

        n = n.nextSibling(); // 移动到下一个节点
    }

    file.close();

    return true;
}

/**
 * @brief RoleManager::deleteAllMonsters 删除所有的怪物
 */
void RoleManager::deleteAllMonsters(void)
{
    QList<BaseRole*>::iterator iter = mFreeMonsterList.begin();
    for(;iter != mFreeMonsterList.end();iter++)
    {
        delete (*iter);
        (*iter) = NULL;
    }

    iter = mActivingMonsterList.begin();
    for(;iter != mActivingMonsterList.end();iter++)
    {
        delete (*iter);
        (*iter) = NULL;
    }

    mFreeMonsterList.clear();
    mActivingMonsterList.clear();
}

/**
 * @brief RoleManager::getFreeMonsters 得到指定数量的空闲怪物
 * @param count
 * @param mapIndex 地图ID
 * @return
 */
QList<BaseRole*> RoleManager::getFreeMonsters(int count,int mapIndex)
{
    QList<BaseRole*> returnroles;

    int tmpCount = 0;
    QList<BaseRole*>::iterator iter = mFreeMonsterList.begin();
    for(;iter != mFreeMonsterList.end();)
    {
        MonsterRole *pMonsterRole = static_cast<MonsterRole*>((*iter));
        if(pMonsterRole == NULL ||
           !pMonsterRole->isExistActivityMap(mapIndex))
        {
            ++iter;
            continue;
        }

        if(tmpCount >= count)
            break;

        returnroles.push_back((*iter));
        mActivingMonsterList.push_back((*iter));

        // 设置NPC当前所在地图
        pMonsterRole->setCurAcitivityMapId(mapIndex);

        // 重置怪物参数
        pMonsterRole->reset();

        print_log(LOG_INFO,
                           "NPC:"+
                           pMonsterRole->getName()+
                           QString::fromLocal8Bit(" ID:")+
                           QString::asprintf("%d",pMonsterRole->getID())+
                           QString::fromLocal8Bit(" 加入地图:")+
                           QString::asprintf("%d",mapIndex)+
                           QString::fromLocal8Bit(" 坐标:")+
                           QString::asprintf("%d,%d",pMonsterRole->getPosition().x(),pMonsterRole->getPosition().y()),
                  "1|0|1");

        iter = mFreeMonsterList.erase(iter);
        tmpCount+=1;
    }    

    return returnroles;
}

/**
 * @brief RoleManager::deleteMonsterFromActinveList 从活动列表中清除指定的怪物
 * @param monster
 */
void RoleManager::deleteMonsterFromActinveList(BaseRole* monster)
{
    if(monster == NULL) return;

    QList<BaseRole*>::iterator iter = qFind(mActivingMonsterList.begin(),
                                            mActivingMonsterList.end(),
                                            monster);
    if(iter == mActivingMonsterList.end())
        return;

    mActivingMonsterList.erase(iter);
}

/**
 * @brief RoleManager::addActivingMonsterToFreeList 将指定怪物加入到空闲怪物列表
 * @param monster
 * @return
 */
bool RoleManager::addActivingMonsterToFreeList(BaseRole* monster)
{
    if(monster == NULL) return false;

    QList<BaseRole*>::iterator iter = qFind(mFreeMonsterList.begin(),
                                            mFreeMonsterList.end(),
                                            monster);
    if(iter != mFreeMonsterList.end())
        return false;

    mFreeMonsterList.push_back(monster);

    return true;
}

/**
 * @brief RoleManager::returnTheMonsters 将死亡怪物重新加入空闲列表中
 * @param monsters
 * @return
 */
int RoleManager::returnTheMonsters(BaseRole* monsters)
{
    if(monsters == NULL || monsters->getRoleType() != ROLETYPE_MONSTER) return 0;

    MonsterRole *pMonsterRole = static_cast<MonsterRole*>(monsters);
    if(pMonsterRole->getState() != ROLESTATE_DEATH)
        return 0;

    // 设置NPC当前所在地图
    pMonsterRole->setCurAcitivityMapId(-1);

    // 从活动列表中清除这个怪物
    deleteMonsterFromActinveList(monsters);

    // 添加空闲列表中
    addActivingMonsterToFreeList(monsters);

    return 1;
}

/**
 * @brief RoleManager::addPlayer 添加一个玩家到系统中
 * @param player
 */
void RoleManager::addPlayer(BaseRole *player)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.find(player->getWebSocket());
    if(iter != mOnlinePlayList.end())
        return;

    mOnlinePlayList[player->getWebSocket()] = player;
}

/**
 * @brief RoleManager::deletePlayer 从系统中清除指定玩家
 * @param player
 */
void RoleManager::deletePlayer(BaseRole *player)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.find(player->getWebSocket());
    if(iter != mOnlinePlayList.end())
    {
        delete iter.value();
        mOnlinePlayList.erase(iter);
    }
}

/**
 * @brief RoleManager::getRoleByWebsocket 根据socket得到指定玩家
 * @param socket
 * @return
 */
BaseRole* RoleManager::getRoleByWebsocket(QWebSocket *socket)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.find(socket);
    if(iter != mOnlinePlayList.end())
        return iter.value();

    return NULL;
}

/**
 * @brief RoleManager::getRoleById 根据ID得到指定的角色
 * @param id
 * @return
 */
BaseRole* RoleManager::getRoleById(int id)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.begin();
    for(;iter != mOnlinePlayList.end();++iter)
    {
        if(iter.value()->getID() == id)
            return iter.value();
    }

    QList<BaseRole*>::iterator itermonster = mActivingMonsterList.begin();
    for(;itermonster != mActivingMonsterList.end();++itermonster)
    {
        if((*itermonster)->getID() == id)
            return (*itermonster);
    }


    return NULL;
}

/**
 * @brief RoleManager::delRoleFromViewList 从可视角色列表中删除指定角色
 * @param role
 * @return
 */
bool RoleManager::delRoleFromViewList(BaseRole *role)
{
    if(role == NULL) return false;

    QList<BaseRole*>::iterator iterrole = mFreeMonsterList.begin();
    for(;iterrole != mFreeMonsterList.end();iterrole++)
    {
        (*iterrole)->delRoleFromViewList(role);
    }
    iterrole = mActivingMonsterList.begin();
    for(;iterrole != mActivingMonsterList.end();iterrole++)
    {
        (*iterrole)->delRoleFromViewList(role);
    }
    QHash<QWebSocket*,BaseRole*>::iterator iterplayer = mOnlinePlayList.begin();
    for(;iterplayer != mOnlinePlayList.end();iterplayer++)
    {
        iterplayer.value()->delRoleFromViewList(role);
    }

    return true;
}

/**
 * @brief RoleManager::deletePlayerByWebsocket 根据socket清除指定的玩家
 * @param socket
 */
void RoleManager::deletePlayerByWebsocket(QWebSocket *socket)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.find(socket);
    if(iter != mOnlinePlayList.end())
    {
        delete iter.value();
        mOnlinePlayList.erase(iter);
    }
}

/**
 * @brief RoleManager::delRoleFromMonsterList 从相关联的NPC列表中删除指定的角色
 * @param role
 */
void RoleManager::delRoleFromMonsterList(BaseRole *role)
{
    QList<BaseRole*>::iterator itermonster = mActivingMonsterList.begin();
    for(;itermonster != mActivingMonsterList.end();++itermonster)
    {
        MonsterRole *pMonsterRole = static_cast<MonsterRole*>((*itermonster));
        if(pMonsterRole && pMonsterRole->getGuardPlayer() &&
           pMonsterRole->getGuardPlayer()->getID() == role->getID())
        {
            pMonsterRole->setState(ROLESTATE_WAITING);
            pMonsterRole->setGuardPlayer(NULL);
        }
    }
}

/**
 * @brief RoleManager::deleteAllPlayers 从系统中清除所有玩家
 */
void RoleManager::deleteAllPlayers(void)
{
    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.begin();
    for(;iter != mOnlinePlayList.end();iter++)
        delete iter.value();

    mOnlinePlayList.clear();
}

/**
 * @brief RoleManager::TransformationAllRoleToJSON 将所有的角色转换成JSON格式
 * @return
 */
QJsonArray RoleManager::TransformationAllRoleToJSON(BaseRole *pBaseRole)
{
    QJsonArray rolearray;
    QHash<QWebSocket*,BaseRole*>::iterator iterplayer = mOnlinePlayList.begin();
    for(;iterplayer != mOnlinePlayList.end();iterplayer++)
    {
        if(iterplayer.value()->getMapIndex() != pBaseRole->getMapIndex())
            continue;

        QJsonObject roleObj;
        roleObj["type"] = iterplayer.value()->getRoleType();
        roleObj["state"] = iterplayer.value()->getState();
        roleObj["id"] = iterplayer.value()->getID();
        roleObj["name"] = iterplayer.value()->getName();
        roleObj["grade"] = iterplayer.value()->getGrade();
        roleObj["posX"] = iterplayer.value()->getPosition().x();
        roleObj["posY"] = iterplayer.value()->getPosition().y();
        roleObj["angle"] = iterplayer.value()->getAngle();
        roleObj["blood"] = iterplayer.value()->getBlood();
        roleObj["defense"] = iterplayer.value()->getDefense();
        roleObj["experience"] = iterplayer.value()->getExperience();
        roleObj["shape"] = iterplayer.value()->getShape();
        roleObj["usingbullet"] = iterplayer.value()->getUsingBullet();

        QJsonObject viewPortObj;
        viewPortObj["x"] = iterplayer.value()->getMapViewRect().x();
        viewPortObj["y"] = iterplayer.value()->getMapViewRect().y();
        viewPortObj["x1"] = iterplayer.value()->getMapViewRect().bottomRight().x();
        viewPortObj["y1"] = iterplayer.value()->getMapViewRect().bottomRight().y();

        roleObj["viewrect"] = viewPortObj;

        QJsonArray bulletArr;
        QMap<int,int> bulletquantitylist = iterplayer.value()->getBulletQuantity();
        QMap<int,int>::iterator iterbullet = bulletquantitylist.begin();
        for(;iterbullet != bulletquantitylist.end();++iterbullet)
        {
            QJsonObject bulletObj;
            bulletObj["id"] = iterbullet.key();
            bulletObj["quantity"] = iterbullet.value();

            bulletArr.push_back(bulletObj);
        }

        roleObj["bulletquantity"] = bulletArr;

        rolearray.push_back(roleObj);
    }
    QList<BaseRole*>::iterator itermonster = mActivingMonsterList.begin();
    for(;itermonster != mActivingMonsterList.end();itermonster++)
    {
        if((*itermonster)->getMapIndex() != pBaseRole->getMapIndex())
            continue;

        QJsonObject roleObj;
        roleObj["type"] = (*itermonster)->getRoleType();
        roleObj["state"] = (*itermonster)->getState();
        roleObj["id"] = (*itermonster)->getID();
        roleObj["name"] = (*itermonster)->getName();
        roleObj["grade"] = (*itermonster)->getGrade();
        roleObj["posX"] = (*itermonster)->getPosition().x();
        roleObj["posY"] = (*itermonster)->getPosition().y();
        roleObj["angle"] = (*itermonster)->getAngle();
        roleObj["blood"] = (*itermonster)->getBlood();
        roleObj["defense"] = (*itermonster)->getDefense();
        roleObj["experience"] = (*itermonster)->getExperience();
        roleObj["shape"] = (*itermonster)->getShape();
        roleObj["usingbullet"] = (*itermonster)->getUsingBullet();

        QJsonObject viewPortObj;
        viewPortObj["x"] = (*itermonster)->getMapViewRect().x();
        viewPortObj["y"] = (*itermonster)->getMapViewRect().y();
        viewPortObj["x1"] = (*itermonster)->getMapViewRect().bottomRight().x();
        viewPortObj["y1"] = (*itermonster)->getMapViewRect().bottomRight().y();

        roleObj["viewrect"] = viewPortObj;

        QJsonArray bulletArr;
        QMap<int,int> bulletquantitylist = (*itermonster)->getBulletQuantity();
        QMap<int,int>::iterator iterbullet = bulletquantitylist.begin();
        for(;iterbullet != bulletquantitylist.end();++iterbullet)
        {
            QJsonObject bulletObj;
            bulletObj["id"] = iterbullet.key();
            bulletObj["quantity"] = iterbullet.value();

            bulletArr.push_back(bulletObj);
        }

        roleObj["bulletquantity"] = bulletArr;

        rolearray.push_back(roleObj);
    }

    return rolearray;
}

/**
 * @brief RoleManager::getSameMapAllRoles 得到指定玩家同地图的所有在线玩家
 * @param role
 * @return
 */
QVector<BaseRole*> RoleManager::getSameMapAllRoles(BaseRole *role)
{
    if(role == NULL || mOnlinePlayList.isEmpty())
        return QVector<BaseRole*>();

    QVector<BaseRole*> tmproles;

    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.begin();
    for(;iter != mOnlinePlayList.end();++iter)
    {
        if(iter.value()->getMapIndex() != role->getMapIndex())
            continue;

        tmproles.push_back(iter.value());
    }

    return tmproles;
}

/**
 * @brief RoleManager::getSameMapOtherRoles 得到同地图的其它在线玩家
 * @param role
 * @return
 */
QVector<BaseRole*> RoleManager::getSameMapOtherRoles(BaseRole *role)
{
    if(role == NULL || mOnlinePlayList.isEmpty())
        return QVector<BaseRole*>();

    QVector<BaseRole*> tmproles;

    QHash<QWebSocket*,BaseRole*>::iterator iter = mOnlinePlayList.begin();
    for(;iter != mOnlinePlayList.end();++iter)
    {
        if(iter.value() == role ||
           iter.value()->getMapIndex() != role->getMapIndex())
            continue;

        tmproles.push_back(iter.value());
    }

    return tmproles;
}

/**
 * @brief RoleManager::update 更新
 */
void RoleManager::update(void)
{
    QHash<int,BaseMap*> tmpBaseMapList = MapManager::getSingleton().getBaseMapList();
    QHash<int,BaseMap*>::iterator iterMap = tmpBaseMapList.begin();
    for(;iterMap != tmpBaseMapList.end();iterMap++)
    {
        // 获取当前地图可以添加的怪物数量
        int tmpMonsterCount = iterMap.value()->getMaxMonsterCount() - iterMap.value()->getTypeRoles(ROLETYPE_MONSTER).size();

        // 检测当前地图怪物数量是否满足
        if(tmpMonsterCount <= 0) continue;

        // 有百分之20的几率将怪物加入到地图中
        if(qrand()%100<20)
        {
            // 取出空闲的怪物
            QList<BaseRole*> freeMonsters = getFreeMonsters(qrand()%tmpMonsterCount,iterMap.value()->getMapIndex());
            QList<BaseRole*>::iterator iterfree = freeMonsters.begin();
            for(;iterfree != freeMonsters.end();iterfree++)
            {
                // 设置地图索引
                (*iterfree)->setMapIndex(iterMap.value()->getMapIndex());

                // 加入到地图中
                iterMap.value()->updateRoleMapTile((*iterfree));
            }
        }
    }
}
